package com.idea.web.filter;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * ����filter�Ļ��ࡣ
 * 
 * @author <a href="woodbird456@gmail.comom">woodbird</a>
 * @version 2011-2-20
 */
public abstract class AbstractFilter implements Filter {
	protected final Logger log = Logger.getLogger(getClass());
	private FilterConfig filterConfig;
	private boolean eatException;

	/**
	 * ��ʼ��filter��
	 * 
	 * @param filterConfig
	 *            filter��������Ϣ
	 * 
	 * @throws ServletException
	 *             ����ʼ��ʧ��
	 */
	public final void init(FilterConfig filterConfig) throws ServletException {
		this.filterConfig = filterConfig;

		this.eatException = Boolean.valueOf(findInitParameter("eatException", "true")).booleanValue();

		if (eatException) {
			log.info("Set eating ServletException to " + eatException);
		}

		init();
	}

	/**
	 * ��ʼ��filter��
	 * 
	 * @throws ServletException
	 *             ����ʼ��ʧ��
	 */
	public void init() throws ServletException {
	}

	/**
	 * ���filter.
	 */
	public void destroy() {
		filterConfig = null;
	}

	/**
	 * ȡ��filter��������Ϣ��
	 * 
	 * @return <code>FilterConfig</code>����
	 */
	public FilterConfig getFilterConfig() {
		return filterConfig;
	}

	/**
	 * ȡ��servlet��������������Ϣ��
	 * 
	 * @return <code>ServletContext</code>����
	 */
	public ServletContext getServletContext() {
		return getFilterConfig().getServletContext();
	}

	/**
	 * ����ָ����filter��ʼ����������˳��
	 * 
	 * <ol>
	 * <li>
	 * ����filter�����<code>init-param</code></li>
	 * <li>
	 * ����webӦ��ȫ�ֵ�<code>init-param</code></li>
	 * <li>
	 * ʹ��ָ��Ĭ��ֵ��</li>
	 * </ol>
	 * 
	 * 
	 * @param paramName
	 *            ��ʼ��������
	 * @param defaultValue
	 *            Ĭ��ֵ
	 * 
	 * @return ָ��������Ӧ�ĳ�ʼ������ֵ�����δ��������ֵΪ�գ��򷵻�<code>null</code>��
	 */
	public String findInitParameter(String paramName, String defaultValue) {
		// ȡfilter����
		String value = trimToNull(getFilterConfig().getInitParameter(paramName));

		// ���δȡ������ȡȫ�ֲ���
		if (value == null) {
			value = trimToNull(getServletContext().getInitParameter(paramName));
		}

		// ���δȡ������ȡĬ��ֵ
		if (value == null) {
			value = defaultValue;
		}

		return value;
	}

	/**
	 * ִ��filter.
	 * 
	 * @param request
	 *            HTTP����
	 * @param response
	 *            HTTP��Ӧ
	 * @param chain
	 *            filter��
	 * 
	 * @throws java.io.IOException
	 *             ����filter��ʱ���������������
	 * @throws ServletException
	 *             ����filter��ʱ�����һ�����
	 */
	public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// ���������filter������exception��
		// ��weblogic�У�servlet forward��jspʱ��jsp�Ի���ô�filter����jsp�׳����쳣�ͻᱻ��filter����
		if (!(request instanceof HttpServletRequest && response instanceof HttpServletResponse) || (request.getAttribute(getClass().getName()) != null)) {
			chain.doFilter(request, response);

			return;
		}

		// ��ֹ����.
		request.setAttribute(getClass().getName(), Boolean.TRUE);

		try {
			// ִ�������doFilter
			HttpServletRequest req = (HttpServletRequest) request;

			HttpServletResponse res = (HttpServletResponse) response;

			doFilter(req, res, chain);
		} catch (ServletException e) {
			if (eatException) {
				log.error("Failed to execute the filter chain", e);
			} else {
				throw e;
			}
		}
	}

	/**
	 * ִ��filter.
	 *
	 * @param request
	 *            HTTP����
	 * @param response
	 *            HTTP��Ӧ
	 * @param chain
	 *            filter��
	 *
	 * @throws java.io.IOException
	 *             ����filter��ʱ���������������
	 * @throws ServletException
	 *             ����filter��ʱ�����һ�����
	 */
	public abstract void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException;

	/**
	 * ���ַ�trim������ַ�Ϊ�հף��򷵻�<code>null</code>��
	 * 
	 * @param str
	 *            �����ַ�
	 * 
	 * @return ����ַ���������ַ�Ϊ�հף��򷵻�<code>null</code>
	 */
	protected String trimToNull(String str) {
		if (str != null) {
			str = str.trim();

			if (str.length() == 0) {
				str = null;
			}
		}

		return str;
	}

	/**
	 * ȡ��request������(HTTP����, URI)
	 * 
	 * @param request
	 *            HTTP����
	 * 
	 * @return �ַ�
	 */
	protected String dumpRequest(HttpServletRequest request) {
		StringBuffer buffer = new StringBuffer(request.getMethod());

		buffer.append(" ").append(request.getRequestURI());

		String queryString = request.getQueryString();
		if (!StringUtils.isEmpty(queryString)) {
			buffer.append("?").append(queryString.trim());
		}

		return buffer.toString();
	}
}
